package bc

import (
	"github.com/flipped-aurora/gin-vue-admin/server/global"
	"github.com/flipped-aurora/gin-vue-admin/server/model/bc"
	bcReq "github.com/flipped-aurora/gin-vue-admin/server/model/bc/request"
	"github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
	"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
	"github.com/flipped-aurora/gin-vue-admin/server/model/server_center"
	"github.com/flipped-aurora/gin-vue-admin/server/service"
	"github.com/flipped-aurora/gin-vue-admin/server/utils"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"math/rand"
	"strconv"
	"sync"
	"time"
)

type BcPhoneApi struct {
}

var bcPhoneService = service.ServiceGroupApp.BcServiceGroup.BcPhoneService
var mapLock = new(sync.Map)

var userBucketMap = make(map[string]*utils.LeakBucket, 0)

// var bucket = utils.NewLeakBucket(30);
var sysLogService = service.ServiceGroupApp.Server_centerServiceGroup.SysLogService

// CreateBcPhone 创建bcPhone表
// @Tags BcPhone
// @Summary 创建bcPhone表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body bc.BcPhone true "创建bcPhone表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
// @Router /bcPhone/createBcPhone [post]
func (bcPhoneApi *BcPhoneApi) CreateBcPhone(c *gin.Context) {
	var bcPhone bc.BcPhone
	err := c.ShouldBindJSON(&bcPhone)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if err := bcPhoneService.CreateBcPhone(&bcPhone); err != nil {
		global.GVA_LOG.Error("创建失败!", zap.Error(err))
		response.FailWithMessage("创建失败", c)
	} else {
		response.OkWithMessage("创建成功", c)
	}
}

// 上传手机号
func (bcPhoneApi *BcPhoneApi) AddPhone(c *gin.Context) {
	var bcPhone bc.BcPhone
	err := c.ShouldBindQuery(&bcPhone)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if bcPhone.Phone == "" {
		global.GVA_LOG.Error("不允许上传空的手机号!", zap.Error(err))
		response.FailWithMessage("不允许上传空的手机号", c)
		return
	}
	data, err := bcProjectService.GetBcProject(uint(bcPhone.ProjectId))
	if err != nil {
		global.GVA_LOG.Error("项目编号不存在错误!", zap.Error(err))
		response.FailWithMessage("项目编号不存在错误", c)
		return
	}
	data1, err := bcPhoneService.GetBcPhoneByProjectIDAndPhone(bcPhone.ProjectId, bcPhone.Phone)
	if data1.ID > 0 {
		global.GVA_LOG.Error("项目已存在相同手机号错误!", zap.Error(err))
		response.FailWithMessage("项目已存在相同手机号错误", c)
		return
	}
	bcPhone.ProjectName = data.ProjectName
	if err := bcPhoneService.CreateBcPhone(&bcPhone); err != nil {
		global.GVA_LOG.Error("创建失败!", zap.Error(err))
		response.FailWithMessage("创建失败", c)
	} else {
		response.OkWithMessage("创建成功", c)
	}
}

func (bcPhoneApi *BcPhoneApi) GetPhoneNum(c *gin.Context) {
	var bcPhone bc.BcPhone
	err := c.ShouldBindQuery(&bcPhone)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	data, err := bcPhoneService.GetBcPhoneList(bcPhone.ProjectId)
	if err != nil {
		global.GVA_LOG.Error("查询失败!", zap.Error(err))
		response.FailWithMessage("查询失败", c)
		return
	}
	response.OkWithData(gin.H{"rebcPhone": len(data)}, c)

}

// DeleteBcPhone 删除bcPhone表
// @Tags BcPhone
// @Summary 删除bcPhone表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body bc.BcPhone true "删除bcPhone表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
// @Router /bcPhone/deleteBcPhone [delete]
func (bcPhoneApi *BcPhoneApi) DeleteBcPhone(c *gin.Context) {
	var bcPhone bc.BcPhone
	err := c.ShouldBindJSON(&bcPhone)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if err := bcPhoneService.DeleteBcPhone(bcPhone); err != nil {
		global.GVA_LOG.Error("删除失败!", zap.Error(err))
		response.FailWithMessage("删除失败", c)
	} else {
		response.OkWithMessage("删除成功", c)
	}
}

// DeleteBcPhoneByIds 批量删除bcPhone表
// @Tags BcPhone
// @Summary 批量删除bcPhone表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.IdsReq true "批量删除bcPhone表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"批量删除成功"}"
// @Router /bcPhone/deleteBcPhoneByIds [delete]
func (bcPhoneApi *BcPhoneApi) DeleteBcPhoneByIds(c *gin.Context) {
	var IDS request.IdsReq
	err := c.ShouldBindJSON(&IDS)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if err := bcPhoneService.DeleteBcPhoneByIds(IDS); err != nil {
		global.GVA_LOG.Error("批量删除失败!", zap.Error(err))
		response.FailWithMessage("批量删除失败", c)
	} else {
		response.OkWithMessage("批量删除成功", c)
	}
}

// UpdateBcPhone 更新bcPhone表
// @Tags BcPhone
// @Summary 更新bcPhone表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body bc.BcPhone true "更新bcPhone表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
// @Router /bcPhone/updateBcPhone [put]
func (bcPhoneApi *BcPhoneApi) UpdateBcPhone(c *gin.Context) {
	var bcPhone bc.BcPhone
	err := c.ShouldBindJSON(&bcPhone)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if err := bcPhoneService.UpdateBcPhone(bcPhone); err != nil {
		global.GVA_LOG.Error("更新失败!", zap.Error(err))
		response.FailWithMessage("更新失败", c)
	} else {
		response.OkWithMessage("更新成功", c)
	}
}

// FindBcPhone 用id查询bcPhone表
// @Tags BcPhone
// @Summary 用id查询bcPhone表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data query bc.BcPhone true "用id查询bcPhone表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
// @Router /bcPhone/findBcPhone [get]
func (bcPhoneApi *BcPhoneApi) FindBcPhone(c *gin.Context) {
	var bcPhone bc.BcPhone
	err := c.ShouldBindQuery(&bcPhone)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if rebcPhone, err := bcPhoneService.GetBcPhone(bcPhone.ID); err != nil {
		global.GVA_LOG.Error("查询失败!", zap.Error(err))
		response.FailWithMessage("查询失败", c)
	} else {
		response.OkWithData(gin.H{"rebcPhone": rebcPhone}, c)
	}
}

// getRandomPhone 随机获取手机号
func (bcPhoneApi *BcPhoneApi) GetRandomPhone(c *gin.Context) {

	var bcPhone bc.BcPhoneReq
	err := c.ShouldBindQuery(&bcPhone)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	if !vaildToken(bcPhone.Token, c) {
		return
	}

	claims, err := utils.GetClaimsByToken(bcPhone.Token)
	if err != nil {
		global.GVA_LOG.Error("token解析失败!", zap.Error(err))
		response.FailWithMessage("token解析失败", c)
		return
	}
	sysUser, err := userService.GetUserInfo(claims.UUID)
	if err != nil {
		global.GVA_LOG.Error("用户查询失败!", zap.Error(err))
		response.FailWithMessage("用户查询失败", c)
		return
	}

	if sysUser.GetCodeStatus != 1 {
		global.GVA_LOG.Error("已被冻结，不许取号!", zap.Error(err))
		response.FailWithMessage("已被冻结，不许取号!", c)
		return
	}
	bucket, ok := userBucketMap[sysUser.Username]
	if !ok {
		bucket = utils.NewLeakBucket(30)
		userBucketMap[sysUser.Username] = bucket
	}
	if !bucket.AccessControl() {
		global.GVA_LOG.Error("访问频繁，请稍后重试!", zap.Error(err))
		response.FailWithMessage("访问频繁，请稍后重试!", c)
		return
	}
	// 项目关闭或者维护的时候不能取号
	data, err := bcProjectService.GetBcProject(uint(bcPhone.ProjectId))
	if err != nil {
		global.GVA_LOG.Error("项目编号不存在错误!", zap.Error(err))
		response.FailWithMessage("项目编号不存在错误", c)
		return
	}
	if data.Status == 1 {
		global.GVA_LOG.Error("项目关闭，不许取号!", zap.Error(err))
		response.FailWithMessage("项目关闭，不许取号!", c)
		return
	}
	if data.Status == 2 {
		global.GVA_LOG.Error("项目维护，不许取号!", zap.Error(err))
		response.FailWithMessage("项目维护，不许取号!", c)
		return
	}

	key := sysUser.Username + "___" + strconv.Itoa(bcPhone.ProjectId)

	// ParseDuration parses a duration string.
	// A duration string is a possibly signed sequence of decimal numbers,
	// each with optional fraction and a unit suffix,
	// such as "300ms", "-1.5h" or "2h45m".
	//  Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
	// 10分钟前
	currentTime := time.Now()
	tenMinutesAgo := currentTime.Add(-10 * time.Minute)
	bcTempList, err := bcTempService.GetBcTempLits(claims.Username, tenMinutesAgo)

	if len(bcTempList) >= 0 && (float64(len(bcTempList)+1)*claims.CustomerPrice > sysUser.Balance) {
		global.GVA_LOG.Error("余额不足", zap.Error(err))
		response.FailWithMessage("余额不足!", c)
		return
	}

	if claims.CustomerPrice > sysUser.Balance {
		global.GVA_LOG.Error("余额不足", zap.Error(err))
		response.FailWithMessage("余额不足!", c)
		return
	}
	//
	user, err := userService.GetUserInfoByCode(claims.SettleOffice, 8881)
	if err != nil {
		global.GVA_LOG.Error("上级用户查询失败!", zap.Error(err))
		response.FailWithMessage("上级用户查询失败", c)
		return
	}
	name := user.Username

	syncData, ok := mapLock.Load(key)
	if !ok {
		syncData = new(sync.Mutex)
		mapLock.Store(key, syncData)
	}
	// 将a转换为sync.Mutex类型
	lock, ok := syncData.(*sync.Mutex)
	if !ok {
		global.GVA_LOG.Error("锁异常!", zap.Error(err))
		response.FailWithMessage("锁异常", c)
		return
	}
	lock.Lock()
	defer lock.Unlock()

	// 获取指定手机号
	if bcPhone.Phone != "" {
		rebcPhone := bcPhoneApi.GetPhone(c, bcPhone)

		//行为加1
		sysLog, err := sysLogService.GetSysLogById(uint(bcPhone.ProjectId), claims.Username, time.Now().Format("2006-01-02"))
		if err != nil {
			global.GVA_LOG.Error("获取数据中心失败!", zap.Error(err))
			response.FailWithMessage("获取数据中心失败", c)
			return
		}
		if sysLog.SysUserName != "" {
			sysLog.GetPhoneNum = sysLog.GetPhoneNum + 1
			sysLogService.UpdateSysLog(sysLog)
		} else {
			sysLogAdd := &server_center.SysLog{
				ProjectId:     bcPhone.ProjectId,
				ProjectName:   data.ProjectName,
				SettleOffice:  claims.SettleOffice,
				SuperiorsName: name,
				SysUserName:   claims.Username,
				GetCodeNum:    0,
				GetPhoneNum:   1,
				SetCodeNum:    0,
			}
			err = sysLogService.CreateSysLog(sysLogAdd)
			if err != nil {
				global.GVA_LOG.Error("创建消费记录失败!", zap.Error(err))
				response.FailWithMessage("释放手机号失败", c)
				return
			}
		}

		rebcAgency, err := bcAgencyService.GetBcAgencyByUser(claims.Username, uint(rebcPhone.ProjectId))
		if err != nil {
			global.GVA_LOG.Error("获取代理失败!", zap.Error(err))
			response.FailWithMessage("获取代理失败", c)
			return
		}

		if rebcAgency.SysUserName == "" {
			bcProject, err := bcProjectService.GetBcProject(uint(rebcPhone.ProjectId))
			if err != nil {
				global.GVA_LOG.Error("项目编号不存在错误!", zap.Error(err))
				response.FailWithMessage("项目编号不存在错误", c)
				return
			}

			bcAgency := &bc.BcAgency{
				AgencyPrice:   bcProject.AgencyPrice,
				CodeType:      bcProject.CodeType,
				Count:         0,
				Price:         claims.CustomerPrice,
				ProjectId:     rebcPhone.ProjectId,
				ProjectName:   rebcPhone.ProjectName,
				SettleOffice:  claims.SettleOffice,
				Status:        0,
				SysUserName:   claims.Username,
				SuperiorsName: name,
			}
			err = bcAgencyService.CreateBcAgency(bcAgency)
			if err != nil {
				global.GVA_LOG.Error("创建代理失败!", zap.Error(err))
				response.FailWithMessage("创建代理失败", c)
				return
			}
		}

		bcTemp := &bc.BcTemp{
			Phone:       rebcPhone.PhoneNumber,
			SysUserName: claims.Username,
		}
		err = bcTempService.CreateBcTemp(bcTemp)
		if err != nil {
			global.GVA_LOG.Error("创建临时记录失败!", zap.Error(err))
			response.FailWithMessage("创建临时记录失败", c)
			return
		}
		response.OkWithDetailed(gin.H{"rebcPhone": rebcPhone.PhoneNumber}, "获取指定手机号成功!", c)
		return
	}

	list, err := bcPhoneService.GetBcPhoneList(bcPhone.ProjectId)
	if err != nil {
		global.GVA_LOG.Error("查询失败!", zap.Error(err))
		response.FailWithMessage("查询失败", c)
		return
	}
	if len(list) <= 0 {
		global.GVA_LOG.Error("没有号池!", zap.Error(err))
		response.FailWithMessage("没有号池", c)
		return
	}
	// 设置随机种子
	rand.Seed(time.Now().UnixNano())
	// 生成一个0到10之间的随机数
	randomNumber := rand.Intn(len(list))
	rebcPhone := list[randomNumber]

	// 获取到指定手机号后再判断是否过期
	if time.Now().Unix() >= rebcPhone.CreatedAt.Unix()+10*60 {
		bcPhoneService.DeleteBcPhoneById(rebcPhone.ID)
		//global.GVA_LOG.Error("获取到已过期手机号!", zap.Error(err))
		response.OkWithMessage("获取到已过期手机号，请重新获取！", c)
		return
	}

	bcRecord := &bc.BcRecord{
		Code:          "",
		PhoneNumber:   rebcPhone.Phone,
		ProjectId:     rebcPhone.ProjectId,
		ProjectName:   rebcPhone.ProjectName,
		SettleOffice:  claims.SettleOffice,
		SuperiorsName: name,
		SysUserName:   claims.Username,
		Status:        0,
		UserPrice:     claims.CustomerPrice, //
	}
	err = bcRecordService.CreateBcRecord(bcRecord)
	if err != nil {
		global.GVA_LOG.Error("创建消费记录失败!", zap.Error(err))
		response.FailWithMessage("释放手机号失败", c)
		return
	}

	rebcAgency, err := bcAgencyService.GetBcAgencyByUser(claims.Username, uint(rebcPhone.ProjectId))
	if err != nil {
		global.GVA_LOG.Error("获取代理失败!", zap.Error(err))
		response.FailWithMessage("获取代理失败", c)
		return
	}

	if rebcAgency.SysUserName == "" {
		bcProject, err := bcProjectService.GetBcProject(uint(rebcPhone.ProjectId))
		if err != nil {
			global.GVA_LOG.Error("项目编号不存在错误!", zap.Error(err))
			response.FailWithMessage("项目编号不存在错误", c)
			return
		}

		bcAgency := &bc.BcAgency{
			AgencyPrice:   bcProject.AgencyPrice,
			CodeType:      bcProject.CodeType,
			Count:         0,
			Price:         claims.CustomerPrice,
			ProjectId:     rebcPhone.ProjectId,
			ProjectName:   rebcPhone.ProjectName,
			SettleOffice:  claims.SettleOffice,
			Status:        0,
			SysUserName:   claims.Username,
			SuperiorsName: name,
		}
		err = bcAgencyService.CreateBcAgency(bcAgency)
		if err != nil {
			global.GVA_LOG.Error("创建代理失败!", zap.Error(err))
			response.FailWithMessage("创建代理失败", c)
			return
		}
	}

	//
	err = bcPhoneService.DeleteBcPhoneById(rebcPhone.ID)
	if err != nil {
		global.GVA_LOG.Error("释放手机号失败!", zap.Error(err))
		response.FailWithMessage("释放手机号失败", c)
		return
	}

	// 格式化日期为指定格式

	sysLog, err := sysLogService.GetSysLogById(uint(rebcPhone.ProjectId), claims.Username, time.Now().Format("2006-01-02"))
	if err != nil {
		global.GVA_LOG.Error("获取数据中心失败!", zap.Error(err))
		response.FailWithMessage("获取数据中心失败", c)
		return
	}
	if sysLog.SysUserName != "" {
		sysLog.GetPhoneNum = sysLog.GetPhoneNum + 1
		sysLogService.UpdateSysLog(sysLog)
	} else {
		sysLogAdd := &server_center.SysLog{
			ProjectId:     rebcPhone.ProjectId,
			ProjectName:   rebcPhone.ProjectName,
			SettleOffice:  claims.SettleOffice,
			SuperiorsName: name,
			SysUserName:   claims.Username,
			GetCodeNum:    0,
			GetPhoneNum:   1,
			SetCodeNum:    0,
		}
		err = sysLogService.CreateSysLog(sysLogAdd)
		if err != nil {
			global.GVA_LOG.Error("创建消费记录失败!", zap.Error(err))
			response.FailWithMessage("释放手机号失败", c)
			return
		}
	}

	bcTemp := &bc.BcTemp{
		Phone:       rebcPhone.Phone,
		SysUserName: claims.Username,
	}
	err = bcTempService.CreateBcTemp(bcTemp)
	if err != nil {
		global.GVA_LOG.Error("创建临时记录失败!", zap.Error(err))
		response.FailWithMessage("创建临时记录失败", c)
		return
	}

	response.OkWithDetailed(gin.H{"rebcPhone": rebcPhone.Phone}, "获取手机号成功!", c)
}

// GetPhone 获取手机号
func (bcPhoneApi *BcPhoneApi) GetPhone(c *gin.Context, bcPhone bc.BcPhoneReq) (bcRecord bc.BcRecord) {
	claims := utils.GetUserInfo(c)
	sysUser, err := userService.GetUserInfo(claims.UUID)
	if err != nil {
		global.GVA_LOG.Error("用户查询失败!", zap.Error(err))
		response.FailWithMessage("用户查询失败", c)
		return
	}
	if sysUser.GetCodeStatus != 1 {
		global.GVA_LOG.Error("已被冻结，不许取号!", zap.Error(nil))
		response.FailWithMessage("已被冻结，不许取号!", c)
		return
	}

	// 从记录里面去获取
	data, err := bcRecordService.GetBcRecordByPhone(bcPhone.ProjectId, bcPhone.Phone)
	if err != nil {
		global.GVA_LOG.Error("查找费记录失败!", zap.Error(err))
		response.FailWithMessage("释放手机号失败", c)
		return
	}
	record := &bc.BcRecord{
		PhoneNumber:   data.PhoneNumber,
		ProjectId:     data.ProjectId,
		ProjectName:   data.ProjectName,
		SettleOffice:  data.SettleOffice,
		SuperiorsName: data.SuperiorsName,
		SysUserName:   data.SysUserName,
		UserPrice:     data.UserPrice,
	}
	err = bcRecordService.CreateBcRecord(record)
	if err != nil {
		global.GVA_LOG.Error("获取指定手机号创建新消费记录失败!", zap.Error(err))
	}

	return *record
}

// GetBcPhoneList 分页获取bcPhone表列表
// @Tags BcPhone
// @Summary 分页获取bcPhone表列表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data query bcReq.BcPhoneSearch true "分页获取bcPhone表列表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /bcPhone/getBcPhoneList [get]
func (bcPhoneApi *BcPhoneApi) GetBcPhoneList(c *gin.Context) {
	var pageInfo bcReq.BcPhoneSearch
	err := c.ShouldBindQuery(&pageInfo)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if list, total, err := bcPhoneService.GetBcPhoneInfoList(pageInfo); err != nil {
		global.GVA_LOG.Error("获取失败!", zap.Error(err))
		response.FailWithMessage("获取失败", c)
	} else {
		response.OkWithDetailed(response.PageResult{
			List:     list,
			Total:    total,
			Page:     pageInfo.Page,
			PageSize: pageInfo.PageSize,
		}, "获取成功", c)
	}
}

func (bcPhoneApi *BcPhoneApi) TestCreateBcPhoneList(c *gin.Context) {
	var pageInfo bcReq.BcPhoneSearch
	err := c.ShouldBindQuery(&pageInfo)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	for i := 1; i < 10000; i++ {
		record := &bc.BcPhone{
			Phone:       strconv.Itoa(i),
			ProjectId:   pageInfo.ProjectId,
			ProjectName: pageInfo.ProjectName,
		}
		err = bcPhoneService.CreateBcPhone(record)
		if err != nil {
			global.GVA_LOG.Error("获取指定手机号池失败!", zap.Error(err))
		}
	}
}
